package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.service.TestService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * @author: atguigu
 * @create: 2023-10-07 08:54
 */
@Slf4j
@Service
public class TestServiceImpl  implements TestService {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    @Override
    public synchronized void testLock() {
        try {
            //1.从Redis缓存中获取key="num"的值  保证redis中存在"num"(手动提前在redis中创建key)
            String value = stringRedisTemplate.opsForValue().get("num");
            if (StringUtils.isBlank(value)) {
                return;
            }
            //2.对获取到值进行+1操作
            int num = Integer.parseInt(value);
            stringRedisTemplate.opsForValue().set("num", String.valueOf(++num));

        } catch (NumberFormatException e) {
            e.printStackTrace();
        }
    }



    @Autowired
    private RedissonClient redissonClient;


    /**
     * 读数据方法
     *
     * @param id
     * @return
     */
    @Override
    public Long read(Long id) {
        //1.创建读写锁对象 锁名称前缀:数据标识
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("myLock:" + id);
        RLock lock = readWriteLock.readLock();

        //2.获取读锁成功 执行读操作  读锁持有期间，不允许并发发写，允许并发读
        try {
            lock.lock(5, TimeUnit.SECONDS);
            log.info(Thread.currentThread().getName() + "执行读数据操作");
            return id;
        } finally {
            //3.释放读锁
            //lock.unlock();
        }
    }



    /**
     * 写数据方法
     *
     * @param id
     */
    @Override
    public void write(Long id) {
        //1.创建读写锁对象 锁名称前缀:数据标识
        RReadWriteLock readWriteLock = redissonClient.getReadWriteLock("myLock:" + id);
        //2.获取写锁成功 执行写操作  写锁持有期间，不允许并发读，并发写
        RLock lock = readWriteLock.writeLock();
        lock.lock(5, TimeUnit.SECONDS);
        try {
            log.info(Thread.currentThread().getName() + "执行写入操作");
        } finally {
            //3.释放写锁
            //lock.unlock();
        }
    }
}
